package drds.plus.sql_process.type.impl;

import drds.plus.sql_process.type.*;

import java.math.BigDecimal;

/**
 * {@link BigDecimal}类型
 */
public class BigDecimalType extends CommonType<BigDecimal> {

    private static final BigDecimal maxValue = BigDecimal.valueOf(Long.MAX_VALUE);
    private static final BigDecimal minValue = BigDecimal.valueOf(Long.MIN_VALUE);
    private final Calculator calculator = new AbstractCalculator() {

        public Object doAdd(Object v1, Object v2) {
            BigDecimal i1 = convert(v1);
            BigDecimal i2 = convert(v2);
            return i1.add(i2);
        }

        public Object doSub(Object v1, Object v2) {
            BigDecimal i1 = convert(v1);
            BigDecimal i2 = convert(v2);
            return i1.subtract(i2);
        }

        public Object doMultiply(Object v1, Object v2) {
            BigDecimal i1 = convert(v1);
            BigDecimal i2 = convert(v2);
            return i1.multiply(i2);
        }

        public Object doDivide(Object v1, Object v2) {
            BigDecimal i1 = convert(v1);
            BigDecimal i2 = convert(v2);

            if (i2.equals(BigDecimal.ZERO)) {
                return null;
            }
            return i1.divide(i2, 4, BigDecimal.ROUND_HALF_UP);
        }

        public Object doMod(Object v1, Object v2) {
            BigDecimal i1 = convert(v1);
            BigDecimal i2 = convert(v2);

            if (i2.equals(BigDecimal.ZERO)) {
                return null;
            }

            return i1.remainder(i2);
        }

    };

    public int encode(Object value, byte[] bytes, int offset) {
        return Encoder.encodeBigDecimal(this.convert(value), bytes, offset);
    }

    public int getLength(Object value) {
        if (value == null) {
            return 1;
        } else {
            return Encoder.calculateEncodedLength(convert(value).toPlainString());
        }
    }

    public DecodeResult decode(byte[] bytes, int offset) {
        BigDecimal[] bigDecimals = new BigDecimal[1];
        int lenght = Decoder.decodeBigDecimalObject(bytes, offset, bigDecimals);
        return new DecodeResult(bigDecimals[0], lenght);
    }

    public BigDecimal incr(Object value) {
        return convert(value).add(BigDecimal.ONE);
    }

    public BigDecimal decr(Object value) {
        return convert(value).subtract(BigDecimal.ONE);
    }

    public BigDecimal getMaxValue() {
        return maxValue;
    }

    public BigDecimal getMinValue() {
        return minValue;
    }

    public Calculator getCalculator() {
        return calculator;
    }

    public int getSqlType() {
        return java.sql.Types.DECIMAL;
    }
}
